package utils

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"hash"
	"io"
)

type headerSorter struct {
	Keys []string
	Vals []string
}

func GetSignedStr(bucketName, objectName, contentType, date, ak, sk string, ossHeader map[string]string) string {
	canonicalizedResource := fmt.Sprintf("/%s/%s", bucketName, objectName)

	hs := NewHeaderSorter(ossHeader)
	canonicalizedOSSHeaders := ""
	for i := range hs.Keys {
		canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
	}

	signStr := "PUT" + "\n" + "" + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
	h := hmac.New(func() hash.Hash { return sha256.New() }, []byte(sk))
	_, _ = io.WriteString(h, signStr)
	signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
	authorizationStr := "OSS " + ak + ":" + signedStr
	return authorizationStr
}

func NewHeaderSorter(m map[string]string) *headerSorter {
	hs := &headerSorter{
		Keys: make([]string, 0, len(m)),
		Vals: make([]string, 0, len(m)),
	}

	for k, v := range m {
		hs.Keys = append(hs.Keys, k)
		hs.Vals = append(hs.Vals, v)
	}
	return hs
}
